using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Windows.Forms;
using System.Reflection;
using System.ComponentModel;

namespace ICSharpCode.WinFormsUI.Controls.NodeControls
{
	public abstract class BaseTextControl : EditableControl
	{
		private Pen _focusPen;
        private StringFormat _format;
        private Graphics _measureGraphics;

        private string _lastLabel = string.Empty;
        private Size _lastSize = new Size();

        #region Properties

        //private Font _font = null;
        //public Font Font
        //{
        //	get
        //	{
        //		if (_font == null)
        //			return Control.DefaultFont;
        //		else
        //			return _font;
        //	}
        //	set
        //	{
        //		if (value == Control.DefaultFont)
        //			_font = null;
        //		else
        //			_font = value;
        //	}
        //}
         
        public Font Font
        {
            get
            {
                if (Parent != null)
                {
                    return Parent.Font;
                }
                return Control.DefaultFont;
            }            
        }

        protected bool ShouldSerializeFont()
		{
            //return (_font != null);
            return true;
		}

		private HorizontalAlignment _textAlign = HorizontalAlignment.Left;
		[DefaultValue(HorizontalAlignment.Left)]
		public HorizontalAlignment TextAlign
		{
			get { return _textAlign; }
			set { _textAlign = value; }
		}

		private StringTrimming _trimming = StringTrimming.None;
		[DefaultValue(StringTrimming.None)]
		public StringTrimming Trimming
		{
			get { return _trimming; }
			set { _trimming = value; }
		}

		#endregion

		protected BaseTextControl()
		{
			_focusPen = new Pen(Color.Black);
			_focusPen.DashStyle = System.Drawing.Drawing2D.DashStyle.Dot;

			_format = new StringFormat(StringFormatFlags.NoWrap | StringFormatFlags.NoClip | StringFormatFlags.FitBlackBox);
			_format.LineAlignment = StringAlignment.Center;

            _measureGraphics = Graphics.FromImage(new Bitmap(1, 1));
        }

		public override Size MeasureSize(NTreeNode node)
		{
			return GetLabelSize(node);
		}

		protected Size GetLabelSize(NTreeNode node)
		{
			return GetLabelSize(GetLabel(node));
		}

		protected Size GetLabelSize(string label)
		{
            if (_lastLabel != label)
            {
                _lastLabel = string.Format("{0}s", label);
                _measureGraphics = Graphics.FromImage(new Bitmap(1, 1));
                SizeF s = _measureGraphics.MeasureString(_lastLabel, Font);
                if (!s.IsEmpty)
                    _lastSize = new Size((int)s.Width, (int)s.Height);
                else
                    _lastSize = new Size(10, Font.Height);
            }
            return _lastSize;			
		}

        private NTreeViewBrushStyle nTreeViewBrushStyle;

        public override void Draw(NTreeNode node, DrawContext context)
		{
			if (context.CurrentEditorOwner == this && node == Parent.CurrentNode)
				return;
            
            if (node.TreeView != null)
            {
                nTreeViewBrushStyle = node.TreeView.TreeViewBrushStyle;
            }
            else
            {
                nTreeViewBrushStyle = new NTreeViewBrushStyle();
            }

			Rectangle clipRect = context.Bounds;
			Brush text = nTreeViewBrushStyle.ControlText;

			string label = GetLabel(node);
			Size s = GetLabelSize(label);
			Rectangle focusRect = new Rectangle(clipRect.X, clipRect.Y, s.Width, clipRect.Height);

			if (context.DrawSelection == DrawSelectionMode.Active)
			{
				text = nTreeViewBrushStyle.HighlightText;
				context.Graphics.FillRectangle(NTreeViewSystemBrushes.Highlight, focusRect);
			}
			else if (context.DrawSelection == DrawSelectionMode.Inactive)
			{
				text = nTreeViewBrushStyle.InactiveText;                 
                context.Graphics.FillRectangle(NTreeViewSystemBrushes.Inactive, focusRect);
            }
			else if (context.DrawSelection == DrawSelectionMode.FullRowSelect)
			{
				text = nTreeViewBrushStyle.HighlightText;
			}

			if (!context.Enabled)
				text = nTreeViewBrushStyle.UnabledText;

			//if (context.DrawFocus)
			//{
			//	focusRect.Width--;
			//	focusRect.Height--;
			//	context.Graphics.DrawRectangle(Pens.Gray, focusRect);
			//	context.Graphics.DrawRectangle(_focusPen, focusRect);
			//}

			_format.Alignment = NTreeNodeTextHelper.TranslateAligment(TextAlign);
			_format.Trimming = Trimming;
			context.Graphics.DrawString(label, context.Font, text, clipRect, _format);
		}

		protected virtual string GetLabel(NTreeNode node)
		{
			if (node.TagNode != null)
			{
				if (string.IsNullOrEmpty(DataPropertyName))
					return node.TagNode.ToString();
				else
				{
					object obj = GetValue(node);
					if (obj != null)
						return obj.ToString();
				}
			}
			return string.Empty;
		}

		protected virtual void SetLabel(NTreeNode node, string value)
		{
			SetValue(node, value);
		}

		protected override void Dispose(bool disposing)
		{
			base.Dispose(disposing);
			if (disposing)
			{
				_focusPen.Dispose();
				_format.Dispose();
			}
		}

	}
}
